package com.cocol.core.ioc;

import android.app.Activity;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import java.lang.reflect.Field;
import java.lang.reflect.Method;

/**
 * 描述：View注入工具
 *
 * @author Cocol
 * @company GuangHeBang
 * @date 2015-10-8
 * @email 617882976@qq.com
 */
public class ViewInjectUtils {
    private static final String TAG = "ViewInjectUtils";

    private static final String METHOD_SET_CONTENT_VIEW = "setContentView";
    private static final String METHOD_FIND_VIEW_BY_ID = "findViewById";

    private static void injectContentView(Activity activity) {
        Class<? extends Activity> actClazz = activity.getClass();

        ContentView contentView = actClazz.getAnnotation(ContentView.class);

        if (contentView != null) {
            int contentViewLayoutId = contentView.value();
            try {
                Method method = actClazz.getMethod(METHOD_SET_CONTENT_VIEW, int.class);
                method.setAccessible(true);
                method.invoke(activity, contentViewLayoutId);
            } catch (Exception e) {
                Log.e(TAG, "注入错误", e);
            }
        }
    }

    private static View injectContentView(Fragment fragment) {
        Class<? extends Fragment> clazz = fragment.getClass();

        ContentView contentView = clazz.getAnnotation(ContentView.class);

        if (contentView != null) {
            int contentViewLayoutId = contentView.value();
            try {
                View view = LayoutInflater.from(fragment.getContext()).inflate(contentViewLayoutId, null, false);
                return view;
            } catch (Exception e) {
                Log.e(TAG, "注入错误", e);
                return null;
            }
        }
        return null;
    }

    private static void injectContentView(ViewGroup view) {
        Class<? extends ViewGroup> actClazz = view.getClass();
        ContentView contentView = actClazz.getAnnotation(ContentView.class);

        if (contentView != null) {
            int contentViewLayoutId = contentView.value();
            try {
                LayoutInflater.from(view.getContext()).inflate(contentViewLayoutId, view);
            } catch (Exception e) {
                Log.e(TAG, "注入错误", e);
            }
        }
    }

    /**
     * @param target 成员变量所在的类
     * @param finder finder.findViewById(activityId);
     */
    private static void injectViews(Object target, Object finder) {
        Class<?> targetClazz = target.getClass();
        Class<?> finderClazz = finder.getClass();
        Field[] fields = targetClazz.getDeclaredFields();

        for (Field field : fields) {
            ViewById viewById = field.getAnnotation(ViewById.class);
            if (viewById != null) {
                int viewId = viewById.value();
                if (viewId != -1) {
                    Log.i(TAG, "注入的控件id：" + viewId);
                    try {
                        Method method = finderClazz.getMethod(METHOD_FIND_VIEW_BY_ID, int.class);
                        Object view = method.invoke(finder, viewId);
                        field.setAccessible(true);
                        // => activity.field = view;
                        field.set(target, view);
                    } catch (Exception e) {
                        Log.e(TAG, "注入错误", e);
                    }
                }
            }
        }
    }

    /**
     * 注入activity
     *
     * @param activity 活动
     */
    public static void inject(Activity activity) {
        injectContentView(activity);
        injectViews(activity, activity);
//        injectEvents(activity, activity);
    }

    /**
     * 注入fragment
     *
     * @param fragment 碎片
     */
    public static View inject(Fragment fragment) {
        View view = injectContentView(fragment);
        if (view != null){
            injectViews(fragment, view);
        }
//        injectEvents(fragment, finder);
        return view;
    }

    /**
     * 用于组合控件，一般在组合控件里面使用
     * @param view 组合控件
     */
    public static void inject(ViewGroup view){
        injectContentView(view);
        injectViews(view, view);
    }
}
